#include "ftdiDevices.h"

#include <signal.h>
#include <termios.h>
#include <unistd.h>

#include <chrono>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <fstream>


#include "usbDataProtocol.h"
#include "timeClickCnt.h"

bool g_exit = false;
void sigint_handler(int sig) {
    printf("捕获到 SIGINT 信号\n");
    printf("处理 SIGINT 信号...\n");
    g_exit = true;
}

int scanKeyboard()
{

    int in;
    struct termios new_settings;
    struct termios stored_settings;
    tcgetattr(STDIN_FILENO,&stored_settings); //获得stdin 输入
    new_settings = stored_settings;           //
    new_settings.c_lflag &= (~ICANON);        //
    new_settings.c_cc[VTIME] = 0;
    tcgetattr(STDIN_FILENO,&stored_settings); //获得stdin 输入
    new_settings.c_cc[VMIN] = 1;
    tcsetattr(STDIN_FILENO,TCSANOW,&new_settings); //

    in = getchar();

    tcsetattr(STDIN_FILENO,TCSANOW,&stored_settings);
    return in;
}

// 获取标准格式的时间字符串
std::string getCurrentTimeString() {
    auto now = std::chrono::system_clock::now();
    auto now_time_t = std::chrono::system_clock::to_time_t(now);
    struct tm timeinfo;
    localtime_r(&now_time_t, &timeinfo);
    
    std::stringstream ss;
    ss << std::put_time(&timeinfo, "%Y_%m_%d_%H_%M_%S");
    return ss.str();
}


void writeHexToFile(std::ofstream& outFile, const uint8_t* data, size_t size) {

    if(size <= 0)
        return;
    if (!outFile.is_open()) {
        std::cerr << "txt Error opening file: " << std::endl;
        return;
    }
    static size_t size_cnt = 0;

    for (size_t i = 0; i < size; ++i) {
        // 将当前字节写入为两位十六进制
        outFile << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[i]);
        ++size_cnt;
        // 处理空格和换行

        if (size_cnt > 0 && (size_cnt) % 50 == 0) {
            outFile << '\n';  // 每50个字节换行
            size_cnt = 0;
        } else {
            outFile << ' ';   // 非行尾则添加空格
        }
        
    }
    
}

void writeHexToParsingFile(std::ofstream& outFile, const uint8_t* data, size_t size) {

    if(size <= 0)
        return;
    if (!outFile.is_open()) {
        std::cerr << "data Error opening file: " << std::endl;
        return;
    }

    for (size_t i = 0; i < size; ++i) {
        // 将当前字节写入为两位十六进制
        outFile << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[i]);      
    }

    outFile << '\n';  
    
}

int main(int argc, char* argv[])
{
    //signal
    struct sigaction new_action, old_action;

    // 设置新的信号处理程序
    new_action.sa_handler = sigint_handler;
    sigemptyset(&new_action.sa_mask); // 清空信号屏蔽集
    new_action.sa_flags = 0;

    // 设置SIGINT信号的新处理程序
    if (sigaction(SIGINT, &new_action, &old_action) == -1) {
        perror("无法设置信号处理程序");
        return 1;
    }

    //param
    // if(argc != 2){
    //     printf("input error param!!!\n");
    //     printf("\n");
    //     printf("please input: read_data filename\n");
    //     printf("\n");
    //     return 0;
    // }
    std::string input_filename = getCurrentTimeString();
    std::shared_ptr<ftdiDevices> app_ptr = std::make_shared<ftdiDevices>();

    std::shared_ptr<UsbDataProtocol> protocol_ptr = std::make_shared<UsbDataProtocol>(8*1024);
    app_ptr->SetVidPid(0x0403, 0x6010);
    // static uint32_t cnt = 0;
    std::string filename = input_filename;
    std::string filename_parsing = input_filename;
    filename.append(".txt");
    filename_parsing.append(".data");
    std::ofstream outFile(filename.c_str(), std::ios::out | std::ios::binary);
    std::ofstream outFile_parsing(filename_parsing.c_str(), std::ios::out | std::ios::binary);
    app_ptr->addCallBack([&protocol_ptr, &outFile](void *param, const uint8_t* data, uint32_t len){
        writeHexToFile(outFile, data, len);
        //解析
        protocol_ptr->pushBuffer(data, len);
    }, nullptr);

    protocol_ptr->addCallBack([&outFile_parsing](void *param, const uint8_t* data, uint32_t len){
        // printf("recv data len:%d\n", len);
        // for(int i = 0; i < len; ++i){
        //     printf("%02x ", data[i]);
        // }
        // printf("\n");
        
        // cnt +=len;
        writeHexToParsingFile(outFile_parsing, data, len);
    }, nullptr);
    if(app_ptr->InitDevice() < 0){
        return 0;
    }

    app_ptr->Start();

    while (1)
    {
        /* code */
        if(g_exit){
            break;
        }
        bool flag = false;
        int input_id = scanKeyboard();
        switch (input_id)
        {
        case 's':
            /* start cap */
            app_ptr->StartCap();
            break;
        case 'q':
            /* stop cap */
            flag = true;
            break;
        
        default:
            break;
        }

        if(flag)
            break;
        std::this_thread::sleep_for(std::chrono::milliseconds(20));
    }
    
    app_ptr->Stop();

    outFile.close();
    outFile_parsing.close();
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));


    return 0;
}